################################################################################
# IMPORTS
################################################################################

from django.conf import settings

from django.contrib.auth.decorators import permission_required

from django.utils.translation import ugettext as _
from django.utils import simplejson

from django.shortcuts import render_to_response
from django.template import RequestContext
from django.http import Http404, HttpResponse

from models import *
from utils import *

################################################################################
# CLASS NoTemplateError
################################################################################

class NoTemplateError(Exception):
    """
    Raised when no template file was specified to render a given instance.
    """
    def __init__(self):
        self.message = 'No template defined for this model instance'
    def __unicode__(self):
        return self.message

################################################################################
# VIEW render
################################################################################

def render(request, path, template_name):
    """
    Render a term.

    Tries to find a term that match in this path and renders is. If the term
    has an associated view bridge, render call the linked view instead of
    rendering and directly return it's response.

    @path: the request path
    @template_name: the template name (including path) to use to render this view
    """
    tname = template_name if template_name else 'taxonomy_render.html'
    term, parameter_string = find_term_and_parameters(path)
    model_instance = None
    instances = []
    if not term:
        # Maybe it's an instance path.
        term, instance_data = find_model_instance_by_path(path)
        if not term:
            raise Http404
        instances = get_related_model_instances(term)
        breadcrumb = [(term.name, term.get_absolute_path()) for term in term.get_breadcrumb()]
        breadcrumb.append((instance_data['data']['title'], instance_data['data']['url']))
        tname = get_model_instance_template_name(instance_data['instance'])
        if not tname:
            raise NoTemplateError()
        model_instance = instance_data['instance']
    else:
        instances = get_related_model_instances(term)
        breadcrumb = [(term.name, term.get_absolute_path()) for term in term.get_breadcrumb()]
        if len(instances) == 1 and term.render_as_instance:
            model_instance = instances[0]['instance']
            tname = get_model_instance_template_name(model_instance)
            if not tname:
                raise NoTemplateError()

    if term.use_bridge:
        return term.call_view(request, parameter_string)

    # If there's a page number pass it along.
    try:
        page = int(request.GET.get('page', '1'))
    except ValueError:
        page = 1

    return render_to_response(
        tname,
        {
            'term':term,
            'page':page,
            'model_instance':model_instance,
            'breadcrumb':breadcrumb
        },
        context_instance=RequestContext(request)
    )

################################################################################
# VIEW taxonomy_admin
################################################################################

@permission_required('term.can_change')
def taxonomy_admin(request):
    if hasattr(settings, 'TAXONOMY_MEDIA_PREFIX'):
        media_prefix = settings.TAXONOMY_MEDIA_PREFIX
    else:
        media_prefix = ''

    if hasattr(settings, 'TAXONOMY_JQUERY_URL'):
        jquery = settings.TAXONOMY_JQUERY_URL
    else:
        jquery = None

    return render_to_response(
        'taxonomy_admin.html',
        {
            'title':_('Taxonomy Administration'),
            'roots':[term for term in get_roots()],
            'root_path':'../',
            'media_prefix':media_prefix,
            'jquery':jquery,
        },
        context_instance=RequestContext(request)
    )

################################################################################
# VIEW taxonomy_ajax_add
################################################################################
@permission_required('term.can_add')
def taxonomy_ajax_add(request):
    response = {'success':False, 'why':_('Invalid Request')}
    if request.method == 'POST':
        lang = get_normalized_language()
        if lang is None:
            response['why'] = _('Invalid Language Code')
        else:
            name = request.POST.get('name', None)
            description = request.POST.get('description', '')
            try:
                parent_id = int(request.POST.get('parent_id', 0))
            except:
                parent_id = 0
            if not name:
                response['why'] = _('A name must be specified for the term')
            else:
                if parent_id:
                    try:
                        parent = Term.objects.get(id=parent_id)
                    except:
                        parent = None
                else:
                    parent = None
                term = Term.objects.create(
                    name=name,
                    description=description,
                    language=lang,
                    parent=parent,
                    weight=65536 # Always add last
                )
                response['success'] = True
                response['why'] = _('Term created')
                response['term_id'] = term.id
                request.user.message_set.create(
                    message=_('%s was created' % (name))
                )
    return HttpResponse(simplejson.dumps(response), mimetype='text/plain')

################################################################################
# VIEW taxonomy_ajax_delete
################################################################################
@permission_required('term.can_delete')
def taxonomy_ajax_delete(request):
    response = {'success':False, 'why':_('Invalid Request')}
    if request.method == 'POST':
        try:
            term = Term.objects.get(id=int(request.POST.get('term_id', 0)))
            if len(Term.objects.filter(parent=term)) > 0:
                response['why'] = _('Term has children')
            else:
                name = term.name
                term.delete()
                response['success'] = True
                response['why'] = _('Term deleted')
                request.user.message_set.create(
                    message=_('%s was deleted' % (name))
                )
        except:
            response['why'] = _('Unknown term')
    return HttpResponse(simplejson.dumps(response), mimetype='text/plain')

################################################################################
# VIEW taxonomy_ajax_detach
################################################################################
@permission_required('term.can_change')
def taxonomy_ajax_detach(request):
    response = {'success':False, 'why':_('Invalid Request')}
    if request.method == 'POST':
        try:
            term = Term.objects.get(id=int(request.POST.get('term_id', 0)))
            term.parent = None
            term.save()
            response['success'] = True
            response['why'] = _('Term detached')
            request.user.message_set.create(
                message=_('%s is now a root term' % (term.name))
            )
        except:
            response['why'] = _('Unknown term')
    return HttpResponse(simplejson.dumps(response), mimetype='text/plain')

################################################################################
# VIEW taxonomy_ajax_attach
################################################################################
@permission_required('term.can_change')
def taxonomy_ajax_attach(request):
    response = {'success':False, 'why':_('Invalid Request')}
    if request.method == 'POST':
        try:
            term = Term.objects.get(id=int(request.POST.get('term_id', 0)))
            parent = Term.objects.get(id=int(request.POST.get('parent_id', 0)))
            if parent != term:
                term.parent = parent
                term.save()
                response['success'] = True
                response['why'] = _('Term attached')
                request.user.message_set.create(
                    message=_('%(term_name)s was attached to %(parent_name)s' % {
                        'term_name':term.name, 'parent_name':parent.name
                    })
                )
            else:
                response['why'] = _('Can not attach to self')
        except:
            response['why'] = _('Unknown term')
    return HttpResponse(simplejson.dumps(response), mimetype='text/plain')

################################################################################
# VIEW taxonomy_ajax_save_tree
################################################################################
@permission_required('term.can_change')
def taxonomy_ajax_save_tree(request):
    response = {'success':False, 'why':_('Invalid Request')}
    if request.method == 'POST':
        tree_ids = None
        tree_indents = None
        for li in request.POST.lists():
            if li[0] == 'tree_ids':
                tree_ids = li[1]
            elif li[0] == 'tree_indents':
                tree_indents = li[1]
        if not (tree_ids and tree_indents) or not (len(tree_ids) == len(tree_indents)):
            response['why'] = _('Invalid Data')
        else:
            try:
                ids = [int(i) for i in tree_ids]
                indents = [int(i) for i in tree_indents]
                stack = [None,]
                current_indent = 0
                last_item = None
                for idx in range(0,len(ids)):
                    indent = indents[idx]
                    id = ids[idx]
                    if indent > current_indent:
                        stack.append(last_item)
                    elif indent < current_indent:
                        for i in range(0, current_indent - indent):
                            stack.pop()
                    current_indent = indent
                    last_item = id
                    term = Term.objects.get(id=id)
                    if stack[-1] is None:
                        parent = None
                    else:
                        parent = Term.objects.get(id=stack[-1])
                    term.parent = parent
                    term.weight = idx
                    term.save()
                response['success'] = True
                response['why'] = _('Tree saved')
                request.user.message_set.create(
                    message=_('Taxonomy tree was saved.')
                )
            except:
                response['why'] = _('Invalid Format')
    return HttpResponse(simplejson.dumps(response), mimetype='text/plain')

